package com.hz.gateway.filter;

import com.hz.utils.UserLoginState;
import io.netty.buffer.UnpooledByteBufAllocator;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.cloud.gateway.filter.GatewayFilterChain;
import org.springframework.cloud.gateway.filter.GlobalFilter;
import org.springframework.core.Ordered;
import org.springframework.core.io.buffer.DataBuffer;
import org.springframework.core.io.buffer.NettyDataBufferFactory;
import org.springframework.data.redis.core.StringRedisTemplate;
import org.springframework.http.HttpStatus;
import org.springframework.http.server.reactive.ServerHttpRequest;
import org.springframework.http.server.reactive.ServerHttpResponse;
import org.springframework.stereotype.Component;
import org.springframework.web.server.ServerWebExchange;
import reactor.core.publisher.Flux;
import reactor.core.publisher.Mono;

import java.io.UnsupportedEncodingException;
import java.util.List;

@Component
public class GatewayFilter implements GlobalFilter, Ordered {
    @Autowired
    StringRedisTemplate redisTemplate;
    /**
     * 验证用户登录状态
     * @param exchange
     * @param chain
     * @return
     */
    @Override
    public Mono<Void> filter(ServerWebExchange exchange, GatewayFilterChain chain) {
        ServerHttpRequest request = exchange.getRequest();
        ServerHttpResponse response = exchange.getResponse();
        String url = request.getURI().toString();

        //判断是否含有token，是否已经登录过
        List<String> tokens = request.getHeaders().get("Authorization");
        if (tokens == null || tokens.size() == 0){
            //1无token
            if (url.contains("/login") || url.contains("/teaccherlogin") || url.contains("/register") || url.contains("/sendcode") || url.contains("/registerbycdk")
                    || url.contains("/captcha.jpg") || url.contains("/oss") || url.contains("/sf") || url.contains("/app") || url.contains("/sys")){
                //登录、注册、发送验证码放行
                return chain.filter(exchange);
            }else{
                //未登录、非法访问
                return Mono.defer(()->{
                    NettyDataBufferFactory nettyDataBufferFactory = new NettyDataBufferFactory(new UnpooledByteBufAllocator(false));
                    response.setStatusCode(HttpStatus.UNAUTHORIZED);
                    byte[] bytes = new byte[0];
                    try {
                        bytes = "{\"code\":\"401\",\"message\":\"Not logged in, Illegal access!\"}".getBytes("utf-8");
                    } catch (UnsupportedEncodingException e) {
                        e.printStackTrace();
                    }
                    DataBuffer buffer = response.bufferFactory().wrap(bytes);
                    response.getHeaders().set("permValid", "false");//设置header
                    response.getHeaders().set("Content-Type", "application/json;charset=utf-8");
                    return response.writeWith(Flux.just(buffer));//设置body
                });
            }
        }else{
            //2有token
            String token = tokens.get(0);
            String user_id = redisTemplate.opsForValue().get("user:" + token);
            if (user_id != null){
                //取到
                //exchange.getSession();
                return chain.filter(exchange);
            }else{
                //未取到
                return Mono.defer(()->{
                    NettyDataBufferFactory nettyDataBufferFactory = new NettyDataBufferFactory(new UnpooledByteBufAllocator(false));
                    response.setStatusCode(HttpStatus.UNAUTHORIZED);
                    byte[] bytes = new byte[0];
                    try {
                        bytes = ("{\"code\":\"401\",\"message\":\""+ UserLoginState.MAC_TOKEN_ERROR+"\"}").getBytes("utf-8");
                    } catch (UnsupportedEncodingException e) {
                        e.printStackTrace();
                    }
                    DataBuffer buffer = response.bufferFactory().wrap(bytes);
                    response.getHeaders().set("permValid", "false");//设置header
                    response.getHeaders().set("Content-Type", "application/json;charset=utf-8");
                    return response.writeWith(Flux.just(buffer));//设置body
                });
            }
        }
    }

    @Override
    public int getOrder() {
        return 0;
    }
}
